//
//  FirstClassValue.swift
//  functional
//
//  Created by LimitLiu on 2019/2/1.
//  Copyright © 2019 LimitLiu. All rights reserved.
//

import UIKit

class FirstClassValue: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.white
    }
    
}

typealias Distance = Double
typealias Region = (Position) -> Bool

struct Position {
    var x: Double
    var y: Double
}

extension Position {
    func inRange(range: Distance) -> Bool {
        return sqrt(x * x + y * y) <= range
    }
    
    func minus(p: Position) -> Position {
        return Position(x: x - p.x, y: y - p.y)
    }
    var lenght: Double {
        return sqrt(x * x + y * y)
    }
}

struct Ship {
    var position: Position
    var firingRange: Distance
    var unsafeRange: Distance
}

extension Ship {
    func canSafelyEngageShip(target: Ship, friendly: Ship) -> Bool {
        let rangeRegion = difference(region: circle(firingRange), minus: circle(unsafeRange))
        let firingRegion = shift(region: rangeRegion, offset: position)
        let friendlyRegion = shift(region: circle(unsafeRange), offset: friendly.position)
        let resultRegion = difference(region: firingRegion, minus: friendlyRegion)
        return resultRegion(target.position)
    }
    
    func circle(_ radius: Distance) -> Region {
        return { point in point.lenght <= radius }
    }
    
    func shift(region: @escaping Region, offset: Position) -> Region {
        return { point in region(point.minus(p: offset)) }
    }
    
    func invert(_ region: @escaping Region) -> Region {
        return { point in !region(point) }
    }
    
    func intersection(_ region1: @escaping Region, _ region2: @escaping Region) -> Region {
        return { point in region1(point) && region2(point) }
    }
    
    func union(_ region1: @escaping Region, _ region2: @escaping Region) -> Region {
        return { point in region1(point) || region2(point) }
    }
    
    func difference(region: @escaping Region, minus: @escaping Region) -> Region {
        return intersection(region, invert(minus))
    }
}
